home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_1.3 / Include-Strip1.3 / startups / startup1.3 / oldrstart / Rstartup.asm < prev    next >
Encoding:
Assembly Source File  |  1988-08-01  |  20.8 KB  |  726 lines

  1.  
  2. *------ Rstartup.asm  v 34.9   Copyright 1988 Commodore-Amiga, Inc.
  3. *------
  4. *------ Conditional assembly flags
  5. *------ ASTART:   1=Standard Globals Defined    0=Reentrant Only
  6. *------ WINDOW:   1=AppWindow for WB startup    0=No AppWindow code
  7. *------ XNIL:     1=Remove Rstartup NIL: init   0=Default Nil: WB Output
  8. *------ DEBUG:    1=Set up old statics for Wack 0=No extra statics
  9.  
  10. * Flags for  [A]start  AWstart  Rstart  RWstart  RXstart
  11. * ASTART         1        1       0        0        0
  12. * WINDOW         0        1       0        1        0
  13. * XNIL           0        0       0        0        1
  14. * DEBUG          0        0       0        0        0
  15.  
  16. ASTART    SET   1
  17. WINDOW    SET   0
  18. XNIL      SET   0
  19. DEBUG     SET   0
  20.  
  21. ;------   Flag WB output initialization
  22. WBOUT     SET   (ASTART!WINDOW!(1-XNIL))
  23.  
  24. ************************************************************************
  25. *
  26. *   Rstartup.asm --- Reentrant C Program Startup/Exit (CLI and WB)
  27. *                    by C. Scheppner, based on Amiga startup.asm
  28. *                    v34.9  05/25/88
  29. *
  30. *   Copyright (c) 1988 Commodore-Amiga, Inc.
  31. *
  32. *   Title to this software and all copies thereof remain vested in the
  33. *   authors indicated in the above copyright notice.  The object version
  34. *   of this code may be used in software for Commodore Amiga computers.
  35. *   All other rights are reserved.
  36. *
  37. *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE
  38. *   ACCURACY, RELIABILITY, PERFORMANCE OR OPERATION OF THIS SOFTWARE,
  39. *   AND ALL SUCH USE IS AT YOUR OWN RISK.  NEITHER COMMODORE NOR THE
  40. *   AUTHORS ASSUME ANY RESPONSIBILITY OR LIABILITY WHATSOEVER WITH
  41. *   RESPECT TO YOUR USE OF THIS SOFTWARE.
  42. *
  43. *
  44. *   RSTARTUP.ASM
  45. *
  46. *      This startup dynamically allocates a structure which includes
  47. *   the argv buffers.  If you use this startup, your code must return
  48. *   to this startup when it exits.  Use exit(n) or final curly brace
  49. *   (rts) to return here.  Do not use AmigaDOS Exit() function.
  50. *   Due to this dynamic allocation and some code consolidation, this
  51. *   startup can make executables several hundred bytes smaller.
  52. *
  53. *       Because a static initialSP variable can not be used, this
  54. *   code depends on the fact that AmigaDOS places the address of
  55. *   the top of our stack in SP and proc->pr_ReturnAddr right before
  56. *   JSR'ing to us.  This code uses pr_ReturnAddr when restoring SP.
  57. *
  58. *       Most versions of Rstartup will initialize a Workbench process's
  59. *   input and output streams (and stdio globals if present) to NIL:
  60. *   if no other form of Workbench output (like WINDOW) is provided.
  61. *   This should help prevent crashes if a user puts an icon on a CLI
  62. *   program, and will also protect against careless stdio debugging
  63. *   or error messages left in a Workbench program.  The code for
  64. *   initializing Workbench IO streams only be removed by assembling
  65. *   Rstartup with ASTART and WINDOW set to 0, and XNIL set to 1.
  66. *
  67. *
  68. *   Some Rstartups which can be conditionally assembled:
  69. *
  70. *      1. Standard Astartup for non-reentrant code
  71. *            Astartup.obj     ASTART=1    WINDOW=0    XNIL=0
  72. *      2. Reentrant startup (no unshareable globals)
  73. *            Rstartup.obj     ASTART=0    WINDOW=0    XNIL=0
  74. *      3. Smaller reentrant-only startup (no NIL: WB init code)
  75. *            RXstartup.obj    ASTART=0    WINDOW=0    XNIL=1
  76. *      4. Standard AWstartup (WB output window) for non-reentrant code
  77. *            AWstartup.obj    ASTART=1    WINDOW=1    XNIL=0
  78. *      5. Reentrant AWstartup (no unshareable globals)
  79. *            RWstartup.obj    ASTART=0    WINDOW=1    XNIL=0
  80. *
  81. *
  82. *   Explanation of conditional assembly flags:
  83. *
  84. *      ASTART (ASTART SET 1) startups will set up and XDEF the
  85. *   global variables _stdin, _stdout, _stderr, _errno and  _WBenchMsg.
  86. *   These startups can be used as smaller replacements for startups
  87. *   like (A)startup.obj and TWstartup.obj.  Startups with ASTART
  88. *   would generally be used for non-reentrant programs, although the
  89. *   startup code itself is still reentrant if the globals are not
  90. *   referenced.
  91. *      Reentrant (ASTART SET 0) startups will NOT set up or
  92. *   XDEF the stdio and WBenchMsg globals.  This not only makes the
  93. *   startup slightly smaller, but also lets you know if your code
  94. *   is referencing these non-reentrant globals (you will get an
  95. *   unresolved external reference when you link).
  96. *
  97. *      WINDOW (WINDOW SET 1) startups use an XREF'd CON: string
  98. *   named AppWindow, defined in your application, to open a stdio
  99. *   console window when your application is started from Workbench.
  100. *   For non-reentrant programs, this window can be used for normal
  101. *   stdio (printf, getchar, etc).  For reentrant programs the window
  102. *   is Input() and Output().  WINDOW is useful when adding Workbench
  103. *   capability to a stdio application, and also for debugging other
  104. *   Workbench applications.  To insure that applications requiring
  105. *   a window startup are linked with a window startup, the label
  106. *   _NeedWStartup can be externed and referenced in the application
  107. *   so that a linker error will occur if linked with a standard
  108. *   startup.
  109. *
  110. *       example:   /* Optional safety reference to NeedWStartup */
  111. *                    extern UBYTE  NeedWStartup;
  112. *                    UBYTE  *HaveWStartup = &NeedWStartup;
  113. *                  /* Required window specification */
  114. *                    char AppWindow[] = "CON:30/30/200/150/MyProgram";
  115. *                    ( OR  char AppWindow[] = "\0";  for no window )
  116. *
  117. *
  118. *      XNIL (XNIL SET 1) allows the creation of a smaller Rstartup
  119. *   by removing the code that initializes a Workbench process's
  120. *   output streams to NIL:.  This flag can only remove the code
  121. *   if it is not required for ASTART or WINDOW.
  122. *
  123. *      DEBUG (DEBUG SET 1) will cause the old startup.asm statics
  124. *   initialSP, dosCmdLen and dosCmdBuf to be defined and initialized
  125. *   by the startup code, for use as debugging symbols when using Wack.
  126. *
  127. *
  128. *   RULES FOR REENTRANT CODE
  129. *
  130. *      - Make no direct or indirect (printf, etc) references to the
  131. *        globals _stdin, _stdout, _stderr, _errno, or _WBenchMsg.
  132. *
  133. *      - For stdio use either special versions of printf and getchar
  134. *        that use Input() and Output() rather than _stdin and _stdout,
  135. *        or use fprintf and fgetc with Input() and Output() file handles.
  136. *
  137. *      - Workbench applications must get the pointer to the WBenchMsg
  138. *        from argv rather than from a global extern WBenchMsg.
  139. *
  140. *      - Use no global or static variables within your code.  Instead,
  141. *        put all former globals in a dynamically allocated structure, and
  142. *        pass around a pointer to that structure.  The only acceptable
  143. *        globals are constants (message strings, etc) and global copies
  144. *        of Library Bases to resolve Amiga.lib references.  Your code
  145. *        must return all OpenLibrary's into non-global variables,
  146. *        copy the result to the global library base only if successful,
  147. *        and use the non-globals when deciding whether to Close any
  148. *        opened libraries.  
  149. *
  150. *
  151. *   By Carolyn Scheppner
  152. *   Based on the following source
  153. ************************************************************************
  154. *
  155. * Source Control:
  156. * --------------
  157. *
  158. * $Header: startup.asm,v 1.1 86/08/25 12:50:07 root Exp $
  159. *
  160. * $Locker: root $
  161. *
  162. * $Log:   startup.asm,v $
  163. * Revision 1.1  86/08/25  12:50:07  root
  164. * Initial revision
  165. *
  166. * Revision 33.6  86/06/12  10:34:36  neil
  167. * changed so any version of dos is OK
  168. * Revision 33.5  86/06/11  19:03:47  neil
  169. * fixed CloseLibrary if open of dos failed
  170. * Revision 33.4  86/06/09  16:48:59  neil
  171. * now processes escapes also
  172. * Revision 33.3  86/06/09  16:18:12  neil
  173. * another checkpoint -- quoted strings now work
  174. * Revision 1.1  85/11/23  13:49:01  neil
  175. * Initial revision
  176. *
  177. ************************************************************************
  178.  
  179.  
  180. ******* Included Files *************************************************
  181.  
  182.    INCLUDE "exec/types.i"
  183.    INCLUDE "exec/alerts.i"
  184.    INCLUDE "exec/memory.i"
  185.    INCLUDE "libraries/dos.i"
  186.    INCLUDE "libraries/dosextens.i"
  187.    INCLUDE "workbench/startup.i"
  188.  
  189.  
  190. ******* Macros *********************************************************
  191.  
  192. xlib   macro
  193.    xref   _LVO\1
  194.    endm
  195.  
  196. callsys   macro
  197.    CALLLIB   _LVO\1
  198.    endm
  199.  
  200. ******* Imported *******************************************************
  201.  
  202.    xref   _AbsExecBase
  203.    xref   _Input
  204.    xref   _Output
  205.    xref   _main         ; C code entry point
  206.  
  207.    IFGT  WINDOW
  208.    xref   _AppWindow    ; CON: spec in application for WB stdio window
  209.    xdef   _NeedWStartup ; May be externed and referenced in application
  210.    ENDC  WINDOW
  211.  
  212.    xlib   Alert
  213.    xlib   AllocMem
  214.    xlib   FindTask
  215.    xlib   Forbid
  216.    xlib   FreeMem
  217.    xlib   GetMsg
  218.    xlib   OpenLibrary
  219.    xlib   CloseLibrary
  220.    xlib   ReplyMsg
  221.    xlib   Wait
  222.    xlib   WaitPort
  223.  
  224.    xlib   CurrentDir
  225.    xlib   Open
  226.    xlib   Close
  227.  
  228. ******* Exported *******************************************************
  229.  
  230. *----- These globals are set up for standard startup code only
  231.    IFGT  ASTART
  232.    xdef   _stdin
  233.    xdef   _stdout
  234.    xdef   _stderr
  235.    xdef   _errno
  236.    xdef   _WBenchMsg
  237.    ENDC  ASTART
  238.  
  239. *----- These globals available to normal and reentrant code
  240.  
  241.    xdef   _SysBase
  242.    xdef   _DOSBase
  243.    xdef   _exit         ; standard C exit function
  244.  
  245.  
  246. ***** Startup Variables structure **********************************
  247.  
  248.   STRUCTURE   SVAR,0
  249.    LONG     sv_DOSBase
  250.    LONG     sv_dosCmdLen
  251.    LONG     sv_dosCmdBuf
  252.    LONG     sv_WBenchMsg
  253.    LONG     sv_WbOutput
  254.    LONG     sv_Reserved1
  255.    LONG     sv_Reserved2
  256.    STRUCT   sv_argvArray,32*4
  257.    STRUCT   sv_argvBuffer,256
  258.   LABEL    SV_SIZEOF
  259.  
  260. ************************************************************************
  261. *
  262. *   Standard Program Entry Point
  263. *
  264. ************************************************************************
  265. *
  266. * Entered with  d0=dosCmdLen  a0=dosCmdBuf
  267. *
  268. * calls  main (argc, argv)
  269. *        int  argc;
  270. *        char *argv[]; 
  271. *
  272. * On Workbench startup, argc=0, argv=WBenchMsg
  273. ************************************************************************
  274.  
  275. startup:
  276.  
  277.    IFGT DEBUG
  278.       move.l   SP,initialSP
  279.       move.l   d0,dosCmdLen
  280.       move.l   a0,dosCmdBuf
  281.    ENDC DEBUG
  282.  
  283.       movem.l  d0/a0,-(sp)
  284.  
  285.       ;------ get Exec's library base pointer:
  286.       movea.l  _AbsExecBase,a6
  287.       move.l   a6,_SysBase
  288.  
  289.       ;------ alloc the argument structure
  290.       move.l   #SV_SIZEOF,d0
  291.       move.l   #(MEMF_PUBLIC!MEMF_CLEAR),d1
  292.       callsys  AllocMem
  293.       move.l   d0,a1             ;allocation to a1
  294.       movem.l  (sp)+,d0/a0       ;d0/a0 and stack to initial state
  295.  
  296.       cmpa.l   #0,a1             ;did we get memory for variables ?
  297.       bne.s    gotmem            ;yes
  298.       moveq.l  #RETURN_FAIL,d0   ;no
  299.       ;------ NOTE:  Exiting here if can't get arg memory
  300.       ;------ Normal exits dependent on ptr to arg memory on stack
  301.       rts
  302.  
  303. gotmem:
  304.       move.l   a1,a5               ;Keep a5 as ptr to SVAR structure
  305.       move.l   a5,-(sp)            ;Put a5 on stack next to Return addr
  306.       move.l   d0,sv_dosCmdLen(a5) ;Save dos command buf len
  307.       move.l   a0,sv_dosCmdBuf(a5) ;     dos command buf ptr
  308.  
  309.       ;------ get the address of our task  a6 = ExecBase
  310.       suba.l   a1,a1               ;clear a1
  311.       callsys  FindTask
  312.       move.l   d0,a4               ;keep task address in a4
  313.  
  314. ;-----------------------------------------------------------------------
  315. ;  Open the DOS library - a6 = AbsExecBase, a5 = svar
  316. ;  If successful, set up Global _DOSBase
  317. ;  Else Alert and exit
  318.  
  319. openDOS
  320.       lea     DOSName(pc),A1     ;dos.library
  321.       moveq.l #0,d0              ;any version
  322.       callsys OpenLibrary
  323.       move.l  d0,sv_DOSBase(a5)
  324.       bne.s   gotDOS             ;Branch if successful
  325.  
  326.       ;----- Else do recoverable alert and exit
  327. noDOS:
  328.       ALERT   (AG_OpenLib!AO_DOSLib)
  329.       moveq.l #100,d0
  330.       bra     exit2
  331.  
  332. gotDOS:
  333.       move.l  d0,_DOSBase        ;Set the global
  334.  
  335. ;-----------------------------------------------------------------------
  336. ;  Branch to Workbench startup code if not a CLI process
  337.  
  338.       tst.l   pr_CLI(A4)
  339.       beq     fromWorkbench
  340.  
  341.  
  342. ;=======================================================================
  343. ;====== CLI Startup Code ===============================================
  344. ;=======================================================================
  345.  
  346. *** Note    a4=Task    a5=SVAR structure    a6=AbsExecBase
  347.  
  348. fromCLI:
  349.       ;------ find command name:
  350.       suba.l   a0,a0
  351.       move.l   pr_CLI(a4),d0
  352.       lsl.l    #2,d0      ; bcpl pointer conversion
  353.       move.l   cli_CommandName(a0,d0.l),d0
  354.       lsl.l    #2,d0      ; bcpl pointer conversion
  355.  
  356.       ;------ create buffer and array:
  357.       movem.l   a2/a3,-(sp)
  358.       lea   sv_argvBuffer(a5),a2
  359.       lea   sv_argvArray(a5),a3
  360.  
  361.       ;------ fetch command name:
  362.       move.l   d0,a0
  363.       moveq.l  #0,d0
  364.       move.b   (a0)+,d0   ; size of command name
  365.       clr.b    0(a0,d0.l)   ; terminate the string
  366.       move.l   a0,(a3)+
  367.  
  368.       ;------   collect parameters:
  369.       move.l   sv_dosCmdLen(a5),d0
  370.       move.l   sv_dosCmdBuf(a5),a0
  371.  
  372.       ;------ null terminate the string, eat trailing garbage
  373.       lea     0(a0,d0.l),a1
  374. stripjunk:
  375.       cmp.b   #' ',-(a1)
  376.  
  377.       ;-- jimm: 8/25/86: per kodiak's recommendation
  378.       ; bls.s   stripjunk
  379.       dbhi   D0,stripjunk
  380.  
  381.       clr.b   1(a1)
  382.  
  383. newarg:
  384.       ;------ skip spaces
  385.       move.b   (a0)+,d1
  386.       beq.s   parmExit
  387.       cmp.b   #' ',d1
  388.       beq.s   newarg
  389.       cmp.b   #9,d1         ; tab
  390.       beq.s   newarg
  391.  
  392.       ;------ push address of the next parameter
  393.       move.l  a2,(a3)+
  394.  
  395.       ;------ process quotes
  396.       cmp.b   #'"',d1
  397.       beq.s   doquote
  398.  
  399.       ;------ copy the parameter in
  400.       move.b  d1,(a2)+
  401.  
  402. nextchar:
  403.       ;------ null termination check
  404.       move.b  (a0)+,d1
  405.       beq.s   parmExit
  406.       cmp.b   #' ',d1
  407.       beq.s   endarg
  408.  
  409.       move.b  d1,(a2)+
  410.       bra.s   nextchar
  411.  
  412. endarg:
  413.       clr.b   (a2)+
  414.       bra.s   newarg
  415.  
  416. doquote:
  417.       ;------ process quoted strings
  418.       move.b  (a0)+,d1
  419.       beq.s   parmExit
  420.       cmp.b   #'"',d1
  421.       beq.s   endarg
  422.  
  423.       ;------ '*' is the BCPL escape character
  424.       cmp.b   #'*',d1
  425.       bne.s   addquotechar
  426.  
  427.       move.b  (a0)+,d1
  428.       cmp.b   #'N',d1
  429.       beq.s   1$
  430.       cmp.b   #'n',d1
  431.       bne.s   2$
  432.  
  433. 1$:
  434.       ;------ got a *N -- turn into a newline
  435.       moveq   #10,d1
  436.       bra.s   addquotechar
  437.  
  438. 2$:
  439.       cmp.b   #'E',d1
  440.       beq.s   3$
  441.       cmp.b   #'e',d1
  442.       bne.s   addquotechar
  443.  
  444. 3$:
  445.       ;------ got a *E -- turn into a escape
  446.       moveq   #27,d1
  447.  
  448. addquotechar:
  449.       move.b  d1,(a2)+
  450.       bra.s   doquote
  451.  
  452. parmExit:
  453.       ;------ all done -- null terminate the baby
  454.       clr.b   (a2)
  455.       clr.l   (a3)
  456.  
  457.       ;------ compute the # of arguments (argc)
  458.       move.l  a3,d0
  459.       lea.l   sv_argvArray(a5),a3
  460.       sub.l   a3,d0
  461.       lsr.l   #2,d0
  462.  
  463.       movem.l  (sp)+,a2/a3
  464.       pea      sv_argvArray(a5)
  465.       move.l   d0,-(sp)
  466.  
  467.  
  468. *
  469. *  The above code relies on the end of line containing a control
  470. *  character of any type, i.e. a valid character must not be the
  471. *  last.  This fact is ensured by DOS.
  472. *
  473.       
  474.    IFGT ASTART
  475.       ;------ get standard input handle:
  476.       jsr      _Input
  477.       move.l   d0,_stdin
  478.  
  479.       ;------ get standard output handle:
  480.       jsr      _Output
  481.       move.l   d0,_stdout
  482.       move.l   d0,_stderr
  483.    ENDC ASTART
  484.  
  485.       bra      domain
  486.  
  487.  
  488. ;=======================================================================
  489. ;====== Workbench Startup Code =========================================
  490. ;=======================================================================
  491.  
  492. *** Note  a4=Task    a5=SVAR structure    a6=AbsExecBase
  493.  
  494. fromWorkbench:
  495.  
  496. ;-----------------------------------------------------------------------
  497. ; This gets the startup message that workbench will send to us
  498. ; Must get this message before doing any DOS calls
  499.  
  500. waitmsg:
  501.       lea   pr_MsgPort(A4),a0     * our process base
  502.       callsys   WaitPort
  503.       lea   pr_MsgPort(A4),a0     * our process base
  504.       callsys GetMsg
  505.  
  506.       ;------ save the message so we can return it later
  507.       move.l   d0,sv_WBenchMsg(a5)
  508.    IFGT ASTART
  509.       move.l   d0,_WBenchMsg
  510.    ENDC ASTART
  511.  
  512.       ;------ push the message on the stack for wbmain (as argv)
  513.       move.l   d0,-(SP)
  514.       clr.l    -(SP)      indicate: run from Workbench (argc==0)
  515.  
  516.       ;------ put DOSBase in a6 for next few calls
  517.       move.l   sv_DOSBase(a5),a6
  518.  
  519.       ;------ get the first argument
  520.       move.l   d0,a2
  521.       move.l   sm_ArgList(a2),d0
  522.       beq.s    docons
  523.  
  524.       ;------ and set the current directory to the same directory
  525.       move.l   d0,a0
  526.       move.l   wa_Lock(a0),d1
  527.       callsys  CurrentDir
  528.  
  529.  
  530. docons: 
  531.    IFGT WBOUT
  532.  
  533.       ;------ Open NIL: or AppWindow for WB Input()/Output() handle
  534.       ;------ Also for possible initialization of stdio globals
  535.       ;------ Stdio used to be initialized to -1
  536.       ;------ a4 = task, a2 = wbenchmsg, DOSBase still in a6
  537.  
  538.       
  539.    IFGT WINDOW
  540.    ;------ Get AppWindow defined in application
  541.       lea.l    _AppWindow,a0
  542.       cmp.b    #0,(a0)
  543.       bne.s    doOpen         ;Open if not null string
  544.    ENDC WINDOW
  545.  
  546.       
  547.    ;------ Open NIL: if no window provided
  548.       lea.l    NilName(PC),a0
  549.  
  550. doOpen:
  551.    ;------ Open up the file whose name is in a0
  552.    ;------ Note - DOSBase still in a6
  553.       move.l   a0,d1
  554.       move.l   #MODE_OLDFILE,d2 
  555.       callsys   Open 
  556.       tst.l    d0
  557.       beq.s    exit2
  558.  
  559.    ;------ save handle for closing on exit
  560.       move.l   d0,sv_WbOutput(a5)
  561.  
  562.    ;------ d0 now contains handle for Workbench Output
  563.  
  564.    IFGT ASTART
  565.    ;------ set the C input and output descriptors 
  566.       move.l   d0,_stdin
  567.       move.l   d0,_stdout
  568.       move.l   d0,_stderr
  569.    ENDC ASTART
  570.  
  571.    ;------ set the console task (so Open( "*", mode ) will work 
  572.    ;       task pointer still in A4
  573.       move.l   d0,pr_CIS(A4)
  574.       move.l   d0,pr_COS(A4)
  575.       lsl.l    #2,d0 
  576.       move.l   d0,a0 
  577.       move.l   fh_Type(a0),d0
  578.       beq.s    noConTask
  579.       move.l   d0,pr_ConsoleTask(A4)
  580. noConTask:
  581.  
  582.    ENDC WBOUT
  583.  
  584.    ;------ Fall though to common WB/CLI code
  585.  
  586.  
  587. ****************************************************
  588. **                                                **
  589. ** This code now used by both CLI and WB startup  **
  590. **                                                **
  591. ****************************************************
  592.  
  593. domain:
  594.       jsr      _main
  595.       ;----- main didn't use exit(n) so provide success return code
  596.       moveq.l  #RETURN_OK,d0
  597.       bra.s    exit2
  598.  
  599. *******************************************************
  600. **                                                   **
  601. **  C Program exit() Function, return code on stack  **
  602. **                                                   **
  603. *******************************************************
  604.  
  605. _exit:
  606.       move.l   4(SP),d0   ;exit(n) return code to d0
  607.  
  608. exit2:
  609.  
  610.       move.l   d0,d2      ;save return code in d2
  611.  
  612.       ;------ restore initial stack ptr
  613.       ;------ FindTask
  614.       movea.l  _AbsExecBase,a6
  615.       suba.l   a1,a1
  616.       callsys  FindTask
  617.       ;------ get SP as it was prior to DOS's jsr to us
  618.       move.l   d0,a4
  619.       move.l   pr_ReturnAddr(a4),a5
  620.       ;------ subtract 4 for return address, 4 for the a5 we pushed
  621.       suba.l   #8,a5
  622.       ;------ restore sp (stack now contains our a5, then address for rts)
  623.       move.l   a5,sp
  624.       ;------ pull our a5 (= ptr to svar)
  625.       move.l   (sp)+,a5
  626.  
  627.       move.l   d2,-(SP)   ;put return code on stack
  628.  
  629.  
  630.    IFGT WBOUT
  631.    ;----- Close any WbOutput file before closing dos.library
  632.       move.l  sv_WbOutput(a5),d1
  633.       beq.s   noWbOut
  634.       move.l  sv_DOSBase(a5),a6
  635.       callsys Close
  636. noWbOut:
  637.       ;------ Restore a6 = ExecBase
  638.       movea.l _AbsExecBase,a6
  639.     ENDC WBOUT
  640.  
  641.       ;------ ExecBase still in a6
  642.       ;------ Close DOS library if it was opened
  643.       move.l   sv_DOSBase(a5),d0
  644.       beq.s    1$
  645.       move.l   d0,a1
  646.       callsys  CloseLibrary
  647. 1$:
  648.  
  649.       ;------ if we ran from CLI, skip workbench reply
  650.       tst.l   sv_WBenchMsg(a5)
  651.       beq.s   deallocSV
  652.  
  653.       ;------ return the startup message to our parent
  654.       ;------   we forbid so workbench can't UnLoadSeg() us
  655.       ;------   before we are done:
  656.       callsys  Forbid
  657.       move.l   sv_WBenchMsg(a5),a1
  658.       callsys  ReplyMsg
  659.  
  660. deallocSV:
  661.       ;------ deallocate the SVAR structure
  662.       move.l  a5,a1
  663.       move.l  #SV_SIZEOF,d0
  664.       callsys FreeMem     ;a6 still holds AbsExecBase
  665.  
  666.       ;------ this rts sends us back to DOS:
  667.  
  668. exitToDOS:
  669.       move.l   (SP)+,d0
  670.       rts
  671.  
  672.  
  673. ;----- PC relative data
  674.  
  675. DOSName      DOSNAME
  676. NilName      dc.b   'NIL:',0
  677.  
  678. ************************************************************************
  679.  
  680.    DATA
  681.  
  682. ************************************************************************
  683.  
  684. _SysBase     dc.l   0
  685. _DOSBase     dc.l   0
  686.  
  687.    IFGT ASTART
  688. _WBenchMsg   dc.l   0
  689. _stdin       dc.l   0
  690. _stdout      dc.l   0
  691. _stderr      dc.l   0
  692. _errno       dc.l   0
  693.    ENDC ASTART
  694.  
  695.    IFGT DEBUG
  696. initialSP    dc.l   0
  697. dosCmdLen    dc.l   0
  698. dosCmdBuf    dc.l   0
  699.    ENDC DEBUG
  700.  
  701. VerRev       dc.w   34,9
  702.    IFGT ASTART
  703.              dc.b   'A'
  704.    ENDC ASTART
  705.    IFEQ ASTART
  706.              dc.b   'R'
  707.    ENDC ASTART
  708.    IFGT WINDOW
  709. _NeedWStartup:
  710.              dc.b   'W'
  711.    ENDC WINDOW
  712.    IFEQ WBOUT
  713.              dc.b   'X'
  714.    ENDC WBOUT
  715.    IFGT DEBUG
  716.              dc.b   'D'
  717.    ENDC DEBUG
  718.  
  719.    END
  720.  
  721.